﻿using System;
using System.Collections.Generic;
using Jayden.Dll.Web.HtmlControls.Descriptions;
using Jayden.Dll.Web.HtmlControls.Generics;

namespace Jayden.Dll.Web.HtmlControls
{
	public class Html : HtmlElement
	{
		public Html() : base(HtmlDescription.Instance) { }

		public Head Head
		{
			get
			{
				List<Head> heads = new List<Head>(GetControls<Head>());
				if(heads.Count == 1)
					return heads[0];
				return null;
			}
		}
		public Body Body
		{
			get
			{
				List<Body> bodies = new List<Body>(GetControls<Body>());
				if (bodies.Count == 1)
					return bodies[0];
				return null;
			}
		}

		public string Manifest { get { return this["manifest"]; } set { this["manifest"] = value; } }
	}

	public class HtmlDescription : HtmlElementDescription
	{
		public static readonly HtmlDescription Instance = new HtmlDescription();
		private HtmlDescription() : base("html") { }
		public override Type ControlType { get { return typeof(Html); } }
		public override string Description { get { return "root of a document."; } }
		public override bool AllowInnerText { get { return false; } }
		public override IEnumerable<HtmlElementDescription> PermittedElements
		{
			get
			{
				yield return HeadDescription.Instance;
				yield return BodyDescription.Instance;
			}
		}

		public override bool CheckValidity(HtmlControl control)
		{
			if (base.CheckValidity(control))
			{
				if (control.Parent != null)
					throw new Exception("<html> must be the root element.");
				Html html = control as Html;
				int head = 0;
				int body = 0;
				foreach (HtmlControl child in html.ChildControls)
				{
					if (child is Head)
					{
						if (body > 0)
							throw new Exception("<head> must be before <body>.");
						if (head > 0)
							throw new Exception("only one <head> is allowed.");
						head++;
					}
					else if (child is Body)
					{
						if (body > 0)
							throw new Exception("only one <body> is allowed.");
						body++;
					}
				}
				return true;
			}
			return false;
		}
	}
}
